﻿using System.IO;
using System.Text;
using System.Windows.Forms;
using System;
using leviathan.player;
using leviathan.scenario;
using leviathan.combat;
using leviathan.puzzle;

namespace leviathan.supervisor
{
    /// <summary>
    /// A fő játék kezelő osztály.
    /// </summary>
    public class Supervisor
    {
        //Supervisor
        public enum Status { idle, newCharacter, newCharacterType, startGame};
        public enum CombatState { endVictory, endDefeat, inner };
        public enum SearchState { endSuccess, endFail, inner };
        CombatState combatStatus;
        SearchState searchStatus;
        Status gameState;
        //Form
        TextBox output;
        Panel navpanel;
        //Game
        Player jatekos;
        Scenario mission;
        
        /// <summary>
        /// Az irányító osztály konstruktora
        /// </summary>
        /// <param name="textbox">A Form1 kiírásra szolgáló textBox objektuma.</param>
        /// <param name="nav">Az egész Formot befedő Panel, amely segítségével el lehet rejteni a felületet.</param>
        public Supervisor(TextBox textbox, Panel nav)
	    {
            gameState = Status.idle;
            combatStatus = CombatState.inner;
            searchStatus = SearchState.inner;
            output = textbox;
            navpanel = nav;
	    }

        /// <summary>
        /// Új karakter létrehozására szolgáló eljárás
        /// </summary>
        /// <param name="name">Az elkészítendő karakter neve.</param>
        /// <param name="type">Az elkészítendő karakter típusa (Harcos, Mágus, íjász).</param>
        /// <param name="race">Az elkészítendő karakter faja.</param>
        public void newCharacter(string name, string type, string race)
        {
            //Karakter értékek
            Int32 elet, mana, tamado, vedo, seb;

            //Új fájl létrehozása
            string path = "../../saves/" + name + ".sav";
            if (!File.Exists(path))
            {
                using (StreamWriter sw = new StreamWriter(path, true))
                {
                    sw.WriteLine(name);                 //Karakternév
                    sw.WriteLine("1");                  //Szint
                    sw.WriteLine("0");                  //Xp
                    sw.WriteLine(race);                 //Faj
                    sw.WriteLine(type);                 //kaszt

                    #region KasztIn
                    if (File.Exists("../../Defaults/" + type + ".def"))
                    {
                        using (StreamReader sr = new StreamReader("../../Defaults/" + type + ".def"))
                        {
                            elet = Convert.ToInt32(sr.ReadLine());        //Életerő
                            mana = Convert.ToInt32(sr.ReadLine());       //Mana
                            tamado = Convert.ToInt32(sr.ReadLine());     //Támadóerő
                            vedo = Convert.ToInt32(sr.ReadLine());       //Védőerő
                            seb = Convert.ToInt32(sr.ReadLine());        //Sebesség
                            sr.Close();
                        }
                    }
                    else
                    {
                        MessageBox.Show("Hiányzó fájl! (kaszt)", "Hiba!");
                        sw.Close();
                        File.Delete(path);
                        return;
                    }
                    #endregion

                    #region FajIn
                    if (File.Exists("../../Defaults/" + race + ".def"))
                    {
                        using (StreamReader sr = new StreamReader("../../Defaults/" + race + ".def"))
                        {
                            //Módosító adatok beolvasása és adatok módosítása
                            elet += Convert.ToInt32(sr.ReadLine());     //Életerő
                            if (0 > elet)
                                elet = 0;
                            mana += Convert.ToInt32(sr.ReadLine());     //Mana
                            if (0 > mana)
                                mana = 0;
                            tamado += Convert.ToInt32(sr.ReadLine());   //Támadóerő
                            if (0 > tamado)
                                tamado = 0;
                            vedo += Convert.ToInt32(sr.ReadLine());     //Védőerő
                            if (0 > vedo)
                                vedo = 0;
                            seb += Convert.ToInt32(sr.ReadLine());      //Sebesség
                            if (0 > seb)
                                seb = 0;
                            //Fájlba írás
                            sw.WriteLine(elet.ToString());              //Életerő
                            sw.WriteLine(mana.ToString());              //Mana
                            sw.WriteLine(tamado.ToString());            //TámadóErő
                            sw.WriteLine(vedo.ToString());              //VédőErő
                            sw.WriteLine(seb.ToString());               //Sebesség
                            sw.WriteLine(sr.ReadLine());                //Alap scenario
                            sr.Close();
                        }
                    }
                    else
                    {
                        MessageBox.Show("Hiányzó fájl! (faj)", "Hiba!");
                        sw.Close();
                        File.Delete(path);
                        return;
                    }
                    #endregion

                    sw.WriteLine("0");                  //Alap Scenario fázis
                    sw.Close();
                }
                setGameState(Status.startGame);
                using (StreamWriter sw = new StreamWriter("../../saves/SaveList.lst", true))
                {
                    sw.WriteLine(name);
                    sw.Close();
                }
                startGame(name);
            }
            else
            {
                setGameState(Status.idle);
                MessageBox.Show("Létező karakter!", "Hiba!");
            }
        }

        /// <summary>
        /// Karakter betöltése
        /// </summary>
        /// <param name="name">A betöltendő karakter neve.</param>
        public void loadCharacter(string name)
        {
            string path = "../../saves/" + name + ".sav";
            if (File.Exists(path))
            {
                setGameState(Status.startGame); 
                startGame(name);
            }
            else
            {
                MessageBox.Show("Nem létező karakter!", "Hiba!");
            }
        }

        /// <summary>
        /// Karakter elmentése
        /// </summary>
        public void saveCharacter()
        {
            string path = "../../saves/" + jatekos.getName() + ".sav";
            if (File.Exists(path))
            {
                using (StreamWriter sw = new StreamWriter(path, false))
                {
                    sw.WriteLine(jatekos.getName());                //Karakternév
                    sw.WriteLine(jatekos.getLevel());               //Szint
                    sw.WriteLine(jatekos.getXp());                  //Xp
                    sw.WriteLine(jatekos.getRace());                //Faj
                    sw.WriteLine(jatekos.getProf());                //Kaszt
                    sw.WriteLine(jatekos.getHp());                  //Életerő
                    sw.WriteLine(jatekos.getMana());                //Mana
                    sw.WriteLine(jatekos.getAp());                  //Támadóerő
                    sw.WriteLine(jatekos.getDp());                  //Védőerő
                    sw.WriteLine(jatekos.getQuickness());           //Gyorsaság
                    sw.WriteLine(jatekos.getScenario());            //Alap Scenario
                    sw.WriteLine(jatekos.getScenarioState());       //Alap Scenario fázis
                    sw.Close();
                }
                MessageBox.Show("Mentés sikeres!", "Mentés!");
            }
            else
            {
                MessageBox.Show("Mentés sikertelen!", "Hiba!");
            }
        }

        /// <summary>
        /// Az aktuális játékállapot lekérdezése
        /// </summary>
        /// <returns>supervisor.Supervisor.Status</returns>
        public Status getGameState()
        {
            return gameState;
        }

        /// <summary>
        /// Az aktuális játékállapot beállítása
        /// </summary>
        /// <param name="st">A beállítani kívánt állapot</param>
        public void setGameState(Status st)
        {
            gameState = st;
        }

        /// <summary>
        /// Az aktuális harcállapot beállítása
        /// </summary>
        /// <param name="st">A beállítani kívánt állapot</param>
        public void setCombatState(CombatState st)
        {
            combatStatus = st;
        }

        /// <summary>
        /// Az aktuális rejtvény állapot beállítása
        /// </summary>
        /// <param name="st">A beállítani kívánt állapot</param>
        public void setSearchState(SearchState st)
        {
            searchStatus = st;
        }

        /// <summary>
        /// A játék indulásakor lefutú metódus.
        /// </summary>
        /// <param name="name">Betöltendő játékos neve.</param>
        public void startGame(string name)
        {
            navpanel.Visible = true;
            output.Text = "Töltés...";
            jatekos = new Player(name);
            mission = new Scenario();
            mission.load(jatekos.getScenario(), jatekos.getScenarioState());
            output.Text = mission.getAct().text;
        }

        /// <summary>
        /// Egy harc végén az eredmény kiértékelésére szolgáló metódus
        /// </summary>
        public void fight(Int16 xp)
        {
            if (CombatState.endVictory == combatStatus)
            {
                mission.choose("left");
                jatekos.setScenarioState(mission.getActNum());
                jatekos.addXp(xp);
                string str = "Szinted: " + jatekos.getLevel() + ". Kaptál: " + xp + " tp-t. ";
                output.Text = str + mission.getAct().text;
            }
            else if (CombatState.endDefeat == combatStatus)
            {
                mission.choose("right");
                jatekos.setScenarioState(mission.getActNum());
                output.Text = mission.getAct().text;
            }
            else
                output.Text = "Nem várt Hiba";
        }

        /// <summary>
        /// Egy keresés végén az eredmény kiértékelésére szolgáló metódus
        /// </summary>
        public void search(Int16 xp)
        {
            if (SearchState.endSuccess == searchStatus)
            {
                mission.choose("left");
                jatekos.setScenarioState(mission.getActNum());
                jatekos.addXp(xp);
                string str = "Szinted: " + jatekos.getLevel() + ". Kaptál: " + xp + " tp-t. ";
                output.Text = str + mission.getAct().text;
            }
            else
            {
                mission.choose("right");
                jatekos.setScenarioState(mission.getActNum());
                output.Text = mission.getAct().text;
            }
            
        }

        /// <summary>
        /// Az outputra való kiírás, illetve a harc, vagy keresés elindítására szolgáló metódus.
        /// </summary>
        public void updateScreen()
        {
            if(mission.getAct().text.StartsWith("FIGHT:"))
            {
                Form fight = new Combat(jatekos, mission.getAct().text.Substring(6), this);
            }
            else if(mission.getAct().text.StartsWith("PUZZLE:"))
            {
                Form puzzle = new Puzzle(mission.getAct().text.Substring(7), this);
            }
            else if (mission.getAct().text.StartsWith("END"))
            {
                output.Text = "Gratulálok, sikeresen végigjátszottad a Leviathan-Rpg játékot. További játékok és frissítések várhatóak.";
            }
            else if (mission.getAct().text.StartsWith("TO:"))
            {
                jatekos.setScenario(mission.getAct().text.Substring(3));
                jatekos.setScenarioState(mission.getAct().left);

                mission = new Scenario();
                mission.load(jatekos.getScenario(), jatekos.getScenarioState());
                output.Text = mission.getAct().text;
            }
            else
            {
                output.Text = mission.getAct().text;
            }
        }

        /// <summary>
        /// Balra lépés kiválasztása
        /// </summary>
        public void chooseLeft()
        {
            mission.choose("left");
            jatekos.setScenarioState(mission.getActNum());
        }

        /// <summary>
        /// Jobbra lépés kiválasztása
        /// </summary>
        public void chooseRight()
        {
            mission.choose("right");
            jatekos.setScenarioState(mission.getActNum());
        }

        /// <summary>
        /// Harc kiválasztása
        /// </summary>
        public void chooseFight()
        {
            mission.choose("fight");
            jatekos.setScenarioState(mission.getActNum());
        }

        /// <summary>
        /// Keresés kiválasztása
        /// </summary>
        public void chooseSearch()
        {
            mission.choose("search");
            jatekos.setScenarioState(mission.getActNum());
        }

        /// <summary>
        /// Cheatek metódusa
        /// </summary>
        /// <param name="num">Cheat típusának száma</param>
        public void code(string s)
        {
            switch (s)
            {
                case "FORTHEHORDE":
                    jatekos.addHp((Int16)1000);
                    break;
                case "42":
                    jatekos.addQuickness((Int16)200);
                    break;
                case "SZOFTEKK":
                    for (int i = 0; i < 10;++i)
                        jatekos.addXp((Int16)100);
                    break;
                case "INROBERTOWETRUST":
                    jatekos.addAp((Int16)300);
                    break;
                case "ROBERTOENCONFIAMOS":
                    jatekos.addDp((Int16)300);
                    break;
            }
        }

        /// <summary>
        /// Az aktuális karakter adatainak kiírása
        /// </summary>
        /// <returns>Karakter adatainak string formájában.</returns>
        public string getStats()
        {
            string str = Environment.NewLine;

            str += "Kaszt: ";
            str += jatekos.getProf();
            str += "; Szint: ";
            str += jatekos.getLevel();
            str += "; Tp: ";
            str += jatekos.getXp();
            str += "; Életerő: ";
            str += jatekos.getHp();
            str += "; Varázserő: ";
            str += jatekos.getMana();
            str += "; Támadóerő: ";
            str += jatekos.getAp();
            str += "; Védőerő: ";
            str += jatekos.getDp();
            str += "; Gyorsaság: ";
            str += jatekos.getQuickness();
            str += ";";
            
            return str;
        }
    }
}